#ifndef RATIONAL_HH
#define RATIONAL_HH

#include <utility>
#include <iostream>
#include <algorithm>
#include <cstdlib>

class Rational {
public:
  
  // CONSTRUCTOR:
  //
  // If the denominator is 0, the behaviour is undefined
  // (you can do whatever you want).
  //
  // You do not need to do any error handling in the constructor.
  Rational(int numerator, int denominator);
  
  // CONSTRUCTOR:
  //
  // This creates a rational number which is equal to the integer "num"
  //
  // You do not need to do any error handling in the constructor.
  Rational(int num);
  
  // copy constructor
  Rational(const Rational&);
  
  // accessors
  int getNumerator() const;
  int getDenominator() const;
  
  // You must implement these operators:
  //
  // +=, -=
  //member binary operator: left-hand operand bound to implicit this pointer
  Rational & operator+=(const Rational & rhs);
  Rational & operator-=(const Rational & rhs);

  // Relational operators
  // <, <=, ==, >=, >, !=

	friend bool operator<(const Rational& lhs, const Rational & rhs);
	friend bool operator<=(const Rational& lhs, const Rational & rhs);
	friend bool operator==(const Rational& lhs, const Rational & rhs);
	friend bool operator>=(const Rational& lhs, const Rational & rhs);
	friend bool operator>(const Rational& lhs, const Rational & rhs);
	friend bool operator!=(const Rational& lhs, const Rational & rhs);

  // Binary operators +, -
  //
  // NOTE: The binary operators + and - should not be members. If they were 
  //       declared as class members, the expression 1 + Rational(1, 2) would 
  //       not work.
  //

  friend Rational operator+(const Rational& lhs, const Rational& rhs);
  friend Rational operator+(int num,const Rational& lhs);
  friend Rational operator-(const Rational& lhs, const Rational& rhs);
  friend Rational operator-(int num,const Rational& lhs);

  // Unary operator -
  Rational operator-();

	// Input and output operators << and >>
  // so the class can be streamed to and streamed from.
  // The rational number is formatted like this:
  // <numerator> <denominator>
  // For example if numerator is 4 and denominator is 5, the output is
  // 4 5
  // 
  // The output stream operators "normalize" the rational number.
  // For example, 2/4 is written to output as "1 2",
  // 1/-2 is written to output as "-1 2" and -2/-4 is written as
  // "1 2".
  //
  // You can implement these operators either as member functions,
  // or nonmember functions in the namespace scope.  
  
  friend std::ostream& operator<< (std::ostream& out, const Rational& rational);
  friend std::istream& operator>> (std::istream& in, Rational& rational);
  
private:
  
  int numerator;
  int denominator;

  // normalize the numerator and denominator, so that the denominator is always positive and
  // the numerator and denominator share no common divisor
  void normalize();
  
  // This function returns the greatest common divisor
  // for a and b. It is useful for normalizing a rational number.
  //
  // For example 6/9, gcd(6, 9) == 3 so we can divide
  // both the numerator and denominator by 3 to get 2/3.
  
  static int gcd(int a, int b)
  {
    using std::swap;
    a = std::abs(a);
    b = std::abs(b);
    if (a>b) swap(a,b);
    while (a)
    {
      	b %= a;
      	swap(a,b);
    }
    return b;
  }
  


};

#endif
